package com.himiotech.core.project.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.himiotech.core.framework.helper.constant.Constants;
import com.himiotech.core.framework.helper.constant.UserConstants;
import com.himiotech.core.framework.helper.exception.HimioException;
import com.himiotech.core.framework.helper.utils.CacheUtils;
import com.himiotech.core.framework.helper.utils.ShiroUtils;
import com.himiotech.core.project.data.mapper.ConfigMapper;
import com.himiotech.core.project.model.entity.Config;
import com.himiotech.core.project.model.metadata.ConfigMetadata;
import com.himiotech.core.project.service.IConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 参数配置 服务层实现
 *
 * @author ruoyi
 * @author wuwenbin
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ConfigServiceImpl extends ServiceImpl<ConfigMapper, Config> implements IConfigService {

    @Autowired
    private ConfigMapper configMapper;

    /**
     * 根据键名查询参数配置信息
     *
     * @param configKey 参数名称
     * @return 参数键值
     */
    @Override
    public String selectConfigByKey(String configKey) {
        String configValue = Convert.toStr(CacheUtils.get(getCacheName(), getCacheKey(configKey)));
        if (StrUtil.isNotEmpty(configValue)) {
            return configValue;
        }
        QueryWrapper<Config> queryWrapper = Wrappers.<Config>query().eq(configKey != null, ConfigMetadata.CONFIG_KEY.getColName(), configKey);
        Config retConfig = configMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNotNull(retConfig)) {
            CacheUtils.put(getCacheName(), getCacheKey(configKey), retConfig.getConfigValue());
            return retConfig.getConfigValue();
        }
        return StrUtil.EMPTY;
    }

    @Override
    public Page<Config> selectConfigListPage(Page<Config> page, Config config) {
        QueryWrapper<Config> query = Wrappers.query();
        if (config != null) {
            query.like(StrUtil.isNotEmpty(config.getConfigKey()), ConfigMetadata.CONFIG_KEY.getColName(), config.getConfigKey())
                    .like(StrUtil.isNotEmpty(config.getConfigName()), ConfigMetadata.CONFIG_NAME.getColName(), config.getConfigName())
                    .eq(StrUtil.isNotEmpty(config.getConfigType()), ConfigMetadata.CONFIG_TYPE.getColName(), config.getConfigType());
            boolean admin = ShiroUtils.getSysUser().isAdmin();
            if (!admin) {
                query.notLike(ConfigMetadata.CONFIG_KEY.getColName(), "sys.pay");
                query.notLike(ConfigMetadata.CONFIG_KEY.getColName(), "sys.admin");
            }
            Map<String, Object> searchParams = config.getSearchParams();
            if (!searchParams.isEmpty()) {
                String start = MapUtil.getStr(searchParams, StrUtil.toCamelCase(ConfigMetadata.GMT_CREATE.getColName()).concat("Start")).concat(" 00:00:00");
                query.ge(StrUtil.isNotEmpty(start), ConfigMetadata.GMT_CREATE.getColName(), start);
                String end = MapUtil.getStr(searchParams, StrUtil.toCamelCase(ConfigMetadata.GMT_CREATE.getColName()).concat("End")).concat(" 23:59:59");
                query.le(StrUtil.isNotEmpty(start), ConfigMetadata.GMT_CREATE.getColName(), end);
            }
        }
        page = configMapper.selectPage(page, query);
        return page;
    }

    /**
     * 新增参数配置
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int insertConfig(Config config) {
        int row = configMapper.insert(config);
        if (row > 0) {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
        return row;
    }

    /**
     * 修改参数配置
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int updateConfig(Config config) {
        int row = configMapper.updateById(config);
        if (row > 0) {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
        return row;
    }

    /**
     * 批量删除参数配置对象
     *
     * @param ids 需要删除的数据ID
     */
    @Override
    public void deleteConfigByIds(String ids) {
        Long[] configIds = Convert.toLongArray(ids.split(","));
        for (Long configId : configIds) {
            Config config = configMapper.selectById(configId);
            if (StrUtil.equals(UserConstants.SYSTEM_DEFAULT, config.getConfigType())) {
                throw new HimioException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
            }
            configMapper.deleteById(configId);
            CacheUtils.remove(getCacheName(), getCacheKey(config.getConfigKey()));
        }
    }

    /**
     * 加载参数缓存数据
     */
    @Override
    public void loadingConfigCache() {
        List<Config> configsList = configMapper.selectList(Wrappers.emptyWrapper());
        for (Config config : configsList) {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
    }

    /**
     * 清空参数缓存数据
     */
    @Override
    public void clearConfigCache() {
        CacheUtils.removeAll(getCacheName());
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }

    /**
     * 校验参数键名是否唯一
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public String checkConfigKeyUnique(Config config) {
        long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
        QueryWrapper<Config> queryWrapper = Wrappers.<Config>query().eq(StrUtil.isNotEmpty(config.getConfigKey()), ConfigMetadata.CONFIG_KEY.getColName(), config.getConfigKey());
        Config info = configMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) {
            return UserConstants.CONFIG_KEY_NOT_UNIQUE;
        }
        return UserConstants.CONFIG_KEY_UNIQUE;
    }

    /**
     * 获取cache name
     *
     * @return 缓存名
     */
    private String getCacheName() {
        return Constants.SYS_CONFIG_CACHE;
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return Constants.SYS_CONFIG_KEY + configKey;
    }
}
